"""
Schoolloop backend

This file is part of polyglot, etc.
"""

import datetime
import requests
import re
import hashlib
from lxml.html import parse
from io import StringIO
from backends.support import Backend, Course, AssignmentGrade, CategoryGrade, AuthTypes, Task

class SchoolloopCourse(Course):
    def __init__(self, backend, row):
        self.row = row
        self.backend = backend

        self.period = row.cssselect(".period")[0].text_content().strip()
        self.title = row.cssselect(".course")[0].text_content().strip()
        self.teacher = row.cssselect(".teacher")[0].text_content().strip()

        if len(row.cssselect(".percent")):
            self.grade_summary = row.cssselect(".percent")[0].text_content().strip()

        self.id = hashlib.md5((self.period + self.title + self.teacher).encode('utf-8')).hexdigest()

    @property
    def grades(self):
        href = self.row.cssselect(".pr_link > a")[0].attrib["href"]
        report = self.backend.session.get(self.backend.base_url + href)

        score_extractor = re.compile("([0-9\.]+) / ([0-9\.]+)")

        pr_root = parse(StringIO(report.text)).getroot()

        categories = {}

        for row in pr_root.cssselect('.module:contains("Scores per Category")')[0].cssselect("tr")[1:]:
            r = row.getchildren()
            category = r[0].text_content().strip()
            weight = r[1].text_content().strip()

            categories[category] = CategoryGrade(category, weight, [])

        for row in pr_root.cssselect(".general_body")[0].getchildren():
            r = row.getchildren()
            category = r[0].getchildren()[0].text.strip()
            assignment = r[0].cssselect("a")[0].text_content().strip()
            due = r[2].text_content().strip()
            (score_numerator, score_denominator) = score_extractor.search(r[3].text_content().strip()).groups()
            comment = r[4].text_content().strip()

            if category in categories:
                categories[category].grades += [AssignmentGrade(assignment, float(score_numerator) / float(score_denominator))]

        return list(categories.values())

    @property
    def tasks(self):
        try:
            return self.backend.tasks_by_course[self.title]
        except KeyError:
            return []

class SchoolloopBackend(Backend):
    Config = ["Username", "Password", "School"]

    def login(self, config):
        # First, fetch the login portal itself
        self.base_url = "https://" + config["School"] + ".schoolloop.com"
        self.session = requests.Session()

        form = self.session.get(self.base_url + "/portal/login")

        # Extract data id
        data_extractor = re.compile('<input type="hidden" name="form_data_id" id="form_data_id" value="(\\d+)">')
        data_id = data_extractor.search(form.text).group(1)

        credentials = {
            "login_name": config["Username"],
            "password": config["Password"],
            "redirect": "",
            "forward": "",
            "login_form_reverse": "",
            "form_data_id": str(data_id),
            "sort": "",
            "reverse": "",
            "login_form_sort": "",
            "event_override": "login",
            "login_form_filter": "",
            "login_form_letter": "",
            "return_url": "",
            "login_form_page_index": "",
            "login_form_page_item_count": ""
        }

        portal = self.session.post(self.base_url + "/portal/login?etarget=login_form", data=credentials)

        # Save session
        self.portal = portal.text
        self.root_element = parse(StringIO(self.portal)).getroot()

        return True

    @property
    def courses(self):
        self.fetch_tasks()

        rows = self.root_element.cssselect(".student_row")
        ret = []

        for row in rows:
            ret += [SchoolloopCourse(self, row)]

        return ret

    def fetch_tasks(self):
        task_list = self.root_element.cssselect('[data-track-container="Active Assignments"]')[0].cssselect('tr')
        self.tasks_by_course = {}

        for rows in task_list:
            r = rows.getchildren()
            title = r[3].text_content().strip()
            course = r[4].text_content().strip()
            due = r[5].text_content().replace("Due:", "").strip() # Help! Internationalisation >_<

            if course not in self.tasks_by_course:
                self.tasks_by_course[course] = []

            self.tasks_by_course[course] += [Task(title, due)]
